package com.highspeed.bdk.service.physical;

import com.highspeed.bdk.bean.entity.ViewPostion;
import com.highspeed.bdk.bean.entity.deploy.AppCpuBindor;
import com.highspeed.bdk.bean.entity.deploy.DeployTopology;
import com.highspeed.bdk.bean.entity.logic.App;
import com.highspeed.bdk.bean.entity.logic.LogicLink;
import com.highspeed.bdk.bean.entity.logic.LogicTopology;
import com.highspeed.bdk.bean.entity.physical.*;
import com.highspeed.bdk.repository.physical.PhysicalTopologyRepository;
import com.highspeed.bdk.service.base.BdkBaseService;
import com.highspeed.bdk.service.deploy.IDeployTopologyService;
import com.highspeed.bdk.service.logic.IAppService;
import com.highspeed.bdk.service.logic.ILogicLinkService;
import com.highspeed.bdk.service.logic.ILogicTopologyService;
import com.highspeed.bdk.utils.PhysicalDeviceUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by chenjiabin on 2018/3/23.
 */
@Service
@Transactional
public class PhysicalTopologyService extends BdkBaseService<PhysicalTopology, Integer> implements IPhysicalTopologyService {
    private static final Log LOG = LogFactory.getLog(PhysicalTopologyService.class);
    @Autowired
    private PhysicalTopologyRepository physicalTopologyRepository;
    @Autowired
    private IPhysicalLinkService physicalLinkService;

    @Autowired
    private IViewPositionService viewPositionService;

    @Autowired
    private IMachineBoxService machineBoxService;

    @Autowired
    private IBoardService boardService;

    @Autowired
    private ILogicTopologyService logicTopologyService;

    @Autowired
    private IDeployTopologyService deployTopologyService;

    @Autowired
    private IAppService appService;

    @Autowired
    private ICpuService cpuService;

    @Autowired
    private IAppCpuBindorService appCpuBindorService;

    @Autowired
    private ILogicLinkService logicLinkService;

    @Override
    public PhysicalTopologyRepository getRepository() {
        return physicalTopologyRepository;
    }

    @Override
    public PhysicalTopology save(PhysicalTopology entity) {
        initPhysicalTopology(entity);
        return super.save(entity);
    }


    @Override
    public PhysicalTopology saveAndFlush(PhysicalTopology entity) {
        initPhysicalTopology(entity);
        return super.saveAndFlush(entity);
    }

    @Override
    public <S extends PhysicalTopology> List<S> save(Iterable<S> entities) {
        if (entities != null) {
            for (PhysicalTopology mb : entities) {
                initPhysicalTopology(mb);
            }
        }
        return super.save(entities);
    }

    @Override
    public void delete(Integer[] ids) {
        if (ids != null) {
            List<PhysicalTopology> tps = new ArrayList<PhysicalTopology>(0);
            for (Integer id : ids) {
                PhysicalTopology old = findOne(id);
                if (old != null) {
                    old.setEnabled(false);
                }
                tps.add(old);
            }
            save(tps);
        }
    }

    @Override
    public void delete(Integer id) {
        delete(new Integer[]{id});
    }

    /**
     * @see IPhysicalLinkService
     */
    @Override
    public List<Map<String, Integer>> queryVirtualLinksByPhysicalTopologyId(Integer id) {
        List<Map<String, Integer>> virtualLinks = new ArrayList<Map<String, Integer>>(0);
        List<PhysicalLink> links = physicalLinkService.findByPhysicalTopologyId(id);
        Map<String, Map<String, Integer>> linkGroup = groupingCountByCpus(links);
        Set<Map.Entry<String, Map<String, Integer>>> entries = linkGroup.entrySet();
        for (Map.Entry<String, Map<String, Integer>> entry : entries) {
            virtualLinks.add(entry.getValue());
        }
        return virtualLinks;
    }

    @Override
    public PhysicalTopology importXml(InputStream is, String name) throws DocumentException {
        // 创建saxReader对象
        SAXReader reader = new SAXReader();
        // 通过read方法读取一个文件 转换成Document对象
        Document document = reader.read(is);
        Map<String, List<Map<String, String>>> allAttributes = new HashMap<>(256);
        //获取根节点元素对象
        Element root = document.getRootElement();
        List<Element> elements = root.elements();
        for (Element element : elements) {
            recursParseNode(root, element, allAttributes);
        }

        //构建物理拓扑
        PhysicalTopology physicalTopology = new PhysicalTopology();
        physicalTopology.setName(name);
        physicalTopology.setCreator("system");
        physicalTopology.setNo("system");
        physicalTopology.setModifier("sytem");
        physicalTopology.setRemark("xml文件导入");

        //保存物理拓扑
        save(physicalTopology);

        //构建主机
        MachineBox machineBox = new MachineBox();
        machineBox.setMachineBoxName("机箱01");
        machineBox.setPhysicalTopology(physicalTopology);
        machineBox.setMachineBoxNo("system");
        machineBox.setRemark("xml文件导入");
        machineBoxService.save(machineBox);
        Map<String, Board> boardMap = new HashMap<>();

        //构建Board
        List<Map<String, String>> all = allAttributes.get("Board");
        if (all != null && !all.isEmpty()) {
            for (int i = 0; i < all.size(); i++) {
                Map<String, String> atrributes = all.get(i);
                Board board = new Board();
                board.setBoardId(atrributes.get("BoardID"));
                board.setBoardModel(Integer.valueOf(atrributes.get("BoardModel")));
                board.setBoardName(atrributes.get("BoardName"));
                board.setBoardSize(Integer.valueOf(atrributes.get("BoardSize")));
                board.setBoardSN(atrributes.get("BoardSN"));
                board.setBoardType(Integer.valueOf(atrributes.get("BoardType")));
                board.setSlotNo(atrributes.get("SlotNo"));
                board.setMachineBox(machineBox);
                boardService.save(board);
                boardMap.put(board.getBoardName(), board);

                //构建视图位置
                String key = "PhysicalViewPostion_Board_physical_" + board.getBoardId();
                List<Map<String, String>> physicalViewPostions = allAttributes.get(key);
                if (physicalViewPostions != null) {
                    for (Map<String, String> pos : physicalViewPostions) {
                        createBoardViewPostion(physicalTopology, board, "PhysicalViewPostion", pos);
                    }
                }
                key = "LogicalViewPostion_Board_logical_" + board.getBoardId();
                List<Map<String, String>> logicalViewPostions = allAttributes.get(key);
                if (logicalViewPostions != null) {
                    for (Map<String, String> pos : physicalViewPostions) {
                        createBoardViewPostion(physicalTopology, board, "LogicalViewPostion", pos);
                    }
                }
            }
        }
        Map<String, Cpu> cpuMap = new HashMap<>();

        //构建Cpu
        all = allAttributes.get("CPU");
        if (all != null && !all.isEmpty()) {
            for (int i = 0; i < all.size(); i++) {
                Map<String, String> atrributes = all.get(i);
                Cpu cpu = new Cpu();
                cpu.setCpuId(atrributes.get("CPUID"));
                cpu.setCpuModel(Integer.valueOf(atrributes.get("CPUModel")));
                cpu.setCpuNetID(atrributes.get("CPUNetID"));
                cpu.setCpuSerial(atrributes.get("CPUSerial"));
                cpu.setCpuType(Integer.valueOf(atrributes.get("CPUType")));
                cpu.setCpuVersion(atrributes.get("CPUVersion"));
                cpu.setSlotNo(atrributes.get("SlotNo"));
                String boardName = atrributes.get("BoardName");
                cpu.setBoard(boardMap.get(boardName));
                cpuService.save(cpu);
                cpuMap.put(cpu.getCpuId(), cpu);

                //构建视图位置
                String key = "PhysicalViewPostion_CPU_physical_" + cpu.getCpuId();
                List<Map<String, String>> physicalViewPostions = allAttributes.get(key);
                if (physicalViewPostions != null) {
                    for (Map<String, String> pos : physicalViewPostions) {
                        createCpuViewPostion(physicalTopology, cpu, "PhysicalViewPostion", pos);
                    }
                }
                key = "LogicalViewPostion_CPU_logical_" + cpu.getCpuId();
                List<Map<String, String>> logicalViewPostions = allAttributes.get(key);
                if (logicalViewPostions != null) {
                    for (Map<String, String> pos : physicalViewPostions) {
                        createCpuViewPostion(physicalTopology, cpu, "LogicalViewPostion", pos);
                    }
                }
            }
        }
        //构建物理链路
        all = allAttributes.get("PhysicalLink");
        if (all != null && !all.isEmpty()) {
            for (int i = 0; i < all.size(); i++) {
                Map<String, String> atrributes = all.get(i);
                PhysicalLink physicalLink = new PhysicalLink();
                physicalLink.setLeftCpu(cpuMap.get(atrributes.get("PhysicalPortACPUID")));
                physicalLink.setRightCpu(cpuMap.get(atrributes.get("PhysicalPortBCPUID")));
                physicalLink.setLeftPort(atrributes.get("PhysicalPortIDA"));
                physicalLink.setRightPort(atrributes.get("PhysicalPortIDB"));
                physicalLink.setPhysicalLinkID(atrributes.get("PhysicalLinkID"));
                physicalLink.setPhysicalLinkLinkStatus(atrributes.get("PhysicalLinkLinkStatus"));
                physicalLink.setLinkQuality(atrributes.get("LinkQuality"));
                physicalLink.setBandwidthAvailable(atrributes.get("BandwidthAvailable"));
                physicalLink.setPhysicalTopology(physicalTopology);
                physicalLinkService.save(physicalLink);
            }
        }

        //构建逻辑拓扑
        LogicTopology logicTopology = new LogicTopology();
        logicTopology.setName("system");
        logicTopology.setNo("no_system");
        logicTopology.setLastModifyTime(new Date());
        logicTopology.setRemark("系统自动生成");

        //构建部署拓扑
        DeployTopology deployTopology = new DeployTopology();
        deployTopology.setPhysicalTopology(physicalTopology);
        deployTopology.setName("部署拓扑");
        deployTopology.setModifier("system");
        deployTopology.setNo("no");

        //构建APP
        Map<String, App> appMap = new HashMap<>();
        all = allAttributes.get("App");
        if (all != null && !all.isEmpty()) {

            //如果app信息存在就保存逻辑拓扑
            logicTopologyService.save(logicTopology);
            deployTopology.setPhysicalTopology(physicalTopology);
            deployTopology.setPreinstalledLogicTopology(logicTopology);
            for (int i = 0; i < all.size(); i++) {
                Map<String, String> atrributes = all.get(i);
                App app = new App();
                app.setLogicTopology(logicTopology);
                app.setName(atrributes.get("AppName"));
                app.setVersion("version1");
                app.setRemark("xml导入");
                appService.save(app);
                appMap.put(atrributes.get("CPUID"), app);
                AppCpuBindor appCpuBindor = new AppCpuBindor();
                appCpuBindor.setApp(app);
                appCpuBindor.setCpu(cpuMap.get(atrributes.get("CPUID")));
                appCpuBindorService.save(appCpuBindor);
                deployTopology.getAcBindors().add(appCpuBindor);
                deployTopologyService.save(deployTopology);
            }
            logicTopologyService.save(logicTopology);
        }
        //构建逻辑链路
        all = allAttributes.get("LogicLink");
        if (all != null && !all.isEmpty()) {
            for (int i = 0; i < all.size(); i++) {
                Map<String, String> atrributes = all.get(i);
                LogicLink logicLink = new LogicLink();
                logicLink.setLeftApp(appMap.get(atrributes.get("AppA")));
                logicLink.setRightApp(appMap.get(atrributes.get("AppB")));
                logicLink.setLeftPort(atrributes.get("LogicalPortIDA"));
                logicLink.setRightPort(atrributes.get("LogicalPortIDB"));
                logicLink.setLogicalLinkType(atrributes.get("LogicalLinkType"));
                logicLink.setLogicalLinkStatus(atrributes.get("LogicalLinkStatus"));
                logicLink.setLogicalLinkSync(atrributes.get("LogicalLinkSync"));
                logicLink.setDirection(atrributes.get("Direction"));
                logicLink.setPortMode(atrributes.get("PortMode"));
                logicLink.setLogicTopology(logicTopology);
                logicLinkService.save(logicLink);
            }
        }
        return null;
    }

    @Override
    public String exportPhysicalToplical(Integer id) {
        StringBuilder sb = new StringBuilder("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n\r");
        sb.append("<Project version=\"081230\">\n\r").append("<RIODataProject/>\n\r");
        Map<String, Object> params = new HashMap<>();

        //处理主板
        params.put("machineBox.physicalTopology.id", id);
        List<Board> boards = boardService.queryToList(params, null);
        sb.append("<Boards>\n\r");
        for (Board board : boards) {
            sb.append("<Board ");
            if (board.getBoardId() == null) {
                sb.append(" BoardID=\"").append(board.getId()).append("\"");
            } else {
                sb.append(" BoardID=\"").append(board.getBoardId()).append("\"");
            }
            sb.append(" SlotNo=\"").append(board.getSlotNo()).append("\"");
            sb.append(" BoardName=\"").append(board.getBoardName()).append("\"");
            sb.append(" BoardType=\"").append(board.getBoardType()).append("\"");
            sb.append(" BoardSize=\"").append(board.getBoardSize()).append("\"");
            sb.append(" BoardModel=\"").append(board.getBoardModel()).append("\"");
            sb.append(" BoardSN=\"").append(board.getBoardSN()).append("\"");
            sb.append(" >\n\r");

            //获取物理视图
            params.clear();
            params.put("topologyId", id);
            params.put("deviceTypeName", "board");
            params.put("deviceId", board.getId());
            params.put("topologyTypeName", "PhysicalViewPostion");
            List<ViewPostion> viewPostions = viewPositionService.queryToList(params, null);
            if (viewPostions != null && !viewPostions.isEmpty()) {
                for (ViewPostion p : viewPostions) {
                    sb.append("<PhysicalViewPostion ");
                    sb.append(" Left=\"").append(p.getX().intValue()).append("\"");
                    sb.append(" Right=\"").append(p.getX().intValue() + p.getWidth().intValue()).append("\"");
                    sb.append(" Top=\"").append(p.getY().intValue()).append("\"");
                    sb.append(" Bottom=\"").append(p.getY().intValue() + p.getHeight().intValue()).append("\"");
                    sb.append(" />\n\r");
                }
            }
            params.put("topologyTypeName", "LogicalViewPostion");
            viewPostions = viewPositionService.queryToList(params, null);
            if (viewPostions != null && !viewPostions.isEmpty()) {
                for (ViewPostion p : viewPostions) {
                    sb.append("<LogicalViewPostion ");
                    sb.append(" Left=\"").append(p.getX().intValue()).append("\"");
                    sb.append(" Right=\"").append(p.getX().intValue() + p.getWidth().intValue()).append("\"");
                    sb.append(" Top=\"").append(p.getY().intValue()).append("\"");
                    sb.append(" Bottom=\"").append(p.getY().intValue() + p.getHeight().intValue()).append("\"");
                    sb.append(" />\n\r");
                }
            }
            sb.append("</Board>\n\r");
        }
        sb.append("</Boards>\n\r");

        //处理CPU
        params.clear();
        params.put("board.machineBox.physicalTopology.id", id);
        List<Cpu> cpus = cpuService.queryToList(params, null);
        sb.append("<CPUs>\n\r");
        for (Cpu cpu : cpus) {
            sb.append("<CPU");
            if (cpu.getCpuId() != null) {
                sb.append(" CPUID=\"").append(cpu.getCpuId()).append("\"");
            } else {
                sb.append(" CPUID=\"").append(cpu.getId()).append("\"");
            }
            sb.append(" MachineBoxNo=\"").append(cpu.getId()).append("\"");
            sb.append(" BoardName=\"").append(cpu.getBoardName()).append("\"");
            sb.append(" BoardType=\"").append(cpu.getBoardType()).append("\"");
            sb.append(" CPUModel=\"").append(cpu.getCpuModel()).append("\"");
            sb.append(" CPUSerial=\"").append(cpu.getCpuSerial()).append("\"");
            sb.append(" CPUType=\"").append(cpu.getCpuType()).append("\"");
            sb.append(" CPUVersion=\"").append(cpu.getCpuVersion()).append("\"");
            sb.append(" CPUNetID=\"").append(cpu.getCpuNetID()).append("\"");
            sb.append(" />\n\r");
            params.clear();
            params.put("topologyId", id);
            params.put("deviceTypeName", "board");
            params.put("deviceId", cpu.getId());
            params.put("topologyTypeName", "PhysicalViewPostion");
            List<ViewPostion> viewPostions = viewPositionService.queryToList(params, null);
            if (viewPostions != null && !viewPostions.isEmpty()) {
                for (ViewPostion p : viewPostions) {
                    sb.append("<LogicalViewPostion ");
                    sb.append(" Left=\"").append(p.getX().intValue()).append("\"");
                    sb.append(" Right=\"").append(p.getX().intValue() + p.getWidth().intValue()).append("\"");
                    sb.append(" Top=\"").append(p.getY().intValue()).append("\"");
                    sb.append(" Bottom=\"").append(p.getY().intValue() + p.getHeight().intValue()).append("\"");
                    sb.append(" />\n\r");
                }
            }
        }
        sb.append("</CPUs>\n\r");
        sb.append("<PhysicalLinks>\n\r");
        params.clear();
        params.put("physicalTopology.id", id);
        List<PhysicalLink> physicalLinks = physicalLinkService.queryToList(params, null);
        if (physicalLinks != null && !physicalLinks.isEmpty()) {
            for (PhysicalLink link : physicalLinks) {
                sb.append("<PhysicalLink ");
                if (link.getPhysicalLinkID() != null) {
                    sb.append(" PhysicalLinkID=\"").append(link.getPhysicalLinkID()).append(" \"");
                } else {
                    sb.append(" PhysicalLinkID=\"").append(link.getId()).append(" \"");
                }
                sb.append(" PhysicalLinkLinkStatus=\"").append(link.getPhysicalLinkLinkStatus()).append(" \"");
                sb.append(" PhysicalPortACPUID=\"").append(link.getLeftCpu().getId()).append(" \"");
                sb.append(" PhysicalPortBCPUID=\"").append(link.getRightCpu().getId()).append(" \"");
                sb.append(" PhysicalPortIDA=\"").append(link.getLeftPort()).append(" \"");
                sb.append(" PhysicalPortIDB=\"").append(link.getRightPort()).append(" \"");
                sb.append(" PhysicalLinkPortMode=\"").append("").append(" \"");
                sb.append(" LinkQuality=\"").append(link.getPhysicalLinkLinkStatus()).append(" \"");
                sb.append(" BandwidthAvailable=\"").append(link.getBandwidthAvailable()).append(" \"");
                sb.append(" />\n\r");
            }
        }
        sb.append("</PhysicalLinks>\n\r");
        params.clear();
        params.put("physicalTopology.id", id);
        List<DeployTopology> deployTopologies = deployTopologyService.queryToList(params, null);
        sb.append("<LogicalLinks>\n\r");
        if (deployTopologies != null && !deployTopologies.isEmpty()) {
            for (DeployTopology deployTopology : deployTopologies) {

                //获得安装的逻辑拓扑
                LogicTopology logicTopology = deployTopology.getPreinstalledLogicTopology();
                params.clear();
                params.put("logicTopology.id", logicTopology.getId());
                List<LogicLink> logicLinks = logicLinkService.queryToList(params, null);
                if (logicLinks != null && !logicLinks.isEmpty()) {
                    for (LogicLink logicLink : logicLinks) {
                        sb.append("<LogicalLink");
                        sb.append(" LogicalLinkID=\"").append(logicLink.getId()).append("\"");
                        sb.append(" LogicalPortIDA=\"").append(logicLink.getLeftPort()).append("\"");
                        sb.append(" AppA=\"").append(logicLink.getLeftApp().getId()).append("\"");
                        sb.append(" LogicalPortIDB=\"").append(logicLink.getRightPort()).append("\"");
                        sb.append(" AppB=\"").append(logicLink.getRightApp().getId()).append("\"");
                        sb.append(" LogicalLinkType=\"").append(logicLink.getLogicalLinkType()).append("\"");
                        sb.append(" LogicalLinkStatus=\"").append(logicLink.getLogicalLinkStatus()).append("\"");
                        sb.append(" LogicalLinkSync=\"").append(logicLink.getLogicalLinkSync()).append("\"");
                        sb.append(" Direction=\"").append(logicLink.getDirection()).append("\"");
                        sb.append(" PortMode=\"").append(logicLink.getPortMode()).append("\"");
                        sb.append("\n\r");
                    }
                }
            }
        }
        sb.append("</LogicalLinks>\n\r");
        sb.append("<Apps>\n\r");
        if (deployTopologies != null && !deployTopologies.isEmpty()) {
            for (DeployTopology d : deployTopologies) {
                List<AppCpuBindor> appCpuBindors = d.getAcBindors();
                for (AppCpuBindor appCpuBindor : appCpuBindors) {
                    sb.append("<APP ");
                    sb.append(" AppID=\"").append(appCpuBindor.getApp().getId()).append("\"");
                    sb.append(" AppName=\"").append(appCpuBindor.getApp().getName()).append("\"");
                    sb.append(" AppNo=\"").append("").append("\"");
                    sb.append(" AppVersion=\"").append(appCpuBindor.getApp().getVersion()).append("\"");
                    sb.append(" CPUID=\"").append(appCpuBindor.getCpu().getId()).append("\"");
                    sb.append(">\n\r");
                }
            }
        }
        sb.append("</Apps>\n\r");
        return sb.toString();
    }

    private void recursParseNode(Element parent, Element element, Map<String, List<Map<String, String>>> allAttributes) {
        parseCurrentNodeAttributes(parent, element, allAttributes);
        List<Element> elements = element.elements();
        for (Element e : elements) {
            recursParseNode(element, e, allAttributes);
        }
    }

    /**
     * 将XML的属性全都读取出来放入map中，待后续操作将属性转化为java实体
     *
     * @param element       当前节点
     * @param allAttributes 存放所有属性的容器
     */
    private void parseCurrentNodeAttributes(Element parent, Element element, Map<String, List<Map<String, String>>> allAttributes) {
        String nodeName = element.getName();
        if ("PhysicalViewPostion".equals(nodeName)) {
            if ("Board".equals(parent.getName())) {
                nodeName = "PhysicalViewPostion_Board_physical_" + parent.attributeValue("BoardID");
            } else if ("CPU".equals(parent.getName())) {
                nodeName = "PhysicalViewPostion_CPU_physical_" + parent.attributeValue("CPUID");
            }
        } else if ("LogicalViewPostion".equals(nodeName)) {
            if ("Board".equals(parent.getName())) {
                nodeName = "LogicalViewPostion_Board_logical_" + parent.attributeValue("BoardID");
            } else if ("CPU".equals(parent.getName())) {
                nodeName = "LogicalViewPostion_CPU_logical_" + parent.attributeValue("CPUID");
            }
        }
        List<Map<String, String>> nodeAttributes = allAttributes.get(nodeName);
        if (nodeAttributes == null) {
            nodeAttributes = new ArrayList<>();
            allAttributes.put(nodeName, nodeAttributes);
        }
        List<Attribute> currentNodeAttributes = element.attributes();
        Map<String, String> attributes = new HashMap<>();
        for (Attribute currentNodeAttribute : currentNodeAttributes) {
            attributes.put(currentNodeAttribute.getName(), currentNodeAttribute.getStringValue());
        }
        nodeAttributes.add(attributes);
    }

    private void createCpuViewPostion(PhysicalTopology physicalTopology, Cpu cpu, String topologyTypeName, Map<String, String> pos) {
        ViewPostion viewPostion = new ViewPostion();
        viewPostion.setTopologyId(physicalTopology.getId());
        viewPostion.setDeviceId(cpu.getId());
        viewPostion.setDeviceTypeName("cpu");
        viewPostion.setIcon("icon");
        viewPostion.setTopologyTypeName(topologyTypeName);
        viewPostion.setX(Double.valueOf(pos.get("Left")));
        viewPostion.setY(Double.valueOf(pos.get("Top")));
        viewPostion.setWidth(new BigDecimal(pos.get("Right")).subtract(new BigDecimal(pos.get("Left"))).doubleValue());
        viewPostion.setHeight(new BigDecimal(pos.get("Bottom")).subtract(new BigDecimal(pos.get("Top"))).doubleValue());
        viewPositionService.save(viewPostion);
    }

    private void createBoardViewPostion(PhysicalTopology physicalTopology, Board board, String topologyTypeName, Map<String, String> pos) {
        ViewPostion viewPostion = new ViewPostion();
        viewPostion.setTopologyId(physicalTopology.getId());
        viewPostion.setDeviceId(board.getId());
        viewPostion.setDeviceTypeName("board");
        viewPostion.setIcon("icon");
        viewPostion.setTopologyTypeName(topologyTypeName);
        viewPostion.setX(Double.valueOf(pos.get("Left")));
        viewPostion.setY(Double.valueOf(pos.get("Top")));
        viewPostion.setWidth(new BigDecimal(pos.get("Right")).subtract(new BigDecimal(pos.get("Left"))).doubleValue());
        viewPostion.setHeight(new BigDecimal(pos.get("Bottom")).subtract(new BigDecimal(pos.get("Top"))).doubleValue());
        viewPositionService.save(viewPostion);
    }


    /**
     * 将物理链接分组统计
     *
     * @param links 物理链接
     * @return 统计结果MAP（KEY为左右两个CPU的ID，VALUE为两个CPU之间的连续数量）
     */
    private Map<String, Map<String, Integer>> groupingCountByCpus(List<PhysicalLink> links) {
        Map<String, Map<String, Integer>> linkGroup = new HashMap<String, Map<String, Integer>>(0);
        for (PhysicalLink link : links) {
            String key = link.getLeftCpu().getId() + "," + link.getRightCpu().getId();
            Map<String, Integer> virtualLink = linkGroup.get(key);
            if (virtualLink == null) {
                virtualLink = new HashMap<String, Integer>(0);
                linkGroup.put(key, virtualLink);
                virtualLink.put("leftCpu", link.getLeftCpu().getId());
                virtualLink.put("rightCpu", link.getRightCpu().getId());
                virtualLink.put("links", 0);
            }
            virtualLink.replace("links", virtualLink.get("links") + 1);
        }
        return linkGroup;
    }

    private void initPhysicalTopology(PhysicalTopology physicalTopology) {
        if (physicalTopology.getCreator() == null) {
            physicalTopology.setCreator(SecurityContextHolder.getContext().getAuthentication().getName());
        }
        PhysicalDeviceUtil.bindParent(physicalTopology.getMachineBoxes(), physicalTopology);
    }

    @Override
    public Page<PhysicalTopology> query(Map<String, Object> params, Pageable pageable) {
        params.put("enabled", true);
        return super.query(params, pageable);
    }

    @Override
    public List<PhysicalTopology> queryDistinctToList(Map<String, Object> params, Pageable pageable) {
        params.put("enabled", true);
        return super.queryDistinctToList(params, pageable);
    }

    @Override
    public List<PhysicalTopology> queryToList(Map<String, Object> params, Pageable pageable) {
        params.put("enabled", true);
        return super.queryToList(params, pageable);
    }

    @Override
    public Page<PhysicalTopology> queryDistinct(Map<String, Object> params, Pageable pageable) {
        params.put("enabled", true);
        return super.queryDistinct(params, pageable);
    }
}
